﻿///////////////////////////////////////////////////////////////////////////////////////////////////////
// Copyright (c) 2023, ООО 1С-Софт
// Все права защищены. Эта программа и сопроводительные материалы предоставляются 
// в соответствии с условиями лицензии Attribution 4.0 International (CC BY 4.0)
// Текст лицензии доступен по ссылке:
// https://creativecommons.org/licenses/by/4.0/legalcode
///////////////////////////////////////////////////////////////////////////////////////////////////////

#Если Сервер Или ТолстыйКлиентОбычноеПриложение Или ВнешнееСоединение Тогда

#Область СлужебныеПроцедурыИФункции

//  Возвращает пользовательский отчет в виде табличного документа.
//  Опирается на значения реквизитов "УзелИнформационнойБазы", "ДополнительнаяРегистрация".
//
//  Параметры:
//       ПолноеИмяМетаданных - Строка - ограничение.
//       Представление       - Строка - параметр результата.
//       УпрощенныйРежим     - Булево - выбор макета.
//
//  Возвращаемое значение:
//      ТабличныйДокумент - отчет.
//
Функция СформироватьТабличныйДокументПользователя(ПолноеИмяМетаданных = "", Представление = "", УпрощенныйРежим = Ложь) Экспорт
	УстановитьПривилегированныйРежим(Истина);
	
	ДанныеКомпоновки = ИнициализироватьКомпоновщик();
	
	Если ПустаяСтрока(ПолноеИмяМетаданных) Тогда
		ДанныеРасшифровки = Новый ДанныеРасшифровкиКомпоновкиДанных;
		ИмяВарианта = "ПользовательскиеДанные"; 
	Иначе
		ДанныеРасшифровки = Неопределено;
		ИмяВарианта = "РасшифровкаПоВидуОбъекта"; 
	КонецЕсли;
	
	// Сохраняем отборы
	НастройкиОтборов = ДанныеКомпоновки.КомпоновщикНастроек.ПолучитьНастройки();
	
	// Нужный вариант
	ДанныеКомпоновки.КомпоновщикНастроек.ЗагрузитьНастройки(
		ДанныеКомпоновки.СхемаКомпоновки.ВариантыНастроек[ИмяВарианта].Настройки);
	
	// Восстанавливаем отборы
	ДобавитьЗначенияОтбораКомпоновки(ДанныеКомпоновки.КомпоновщикНастроек.Настройки.Отбор.Элементы, 
		НастройкиОтборов.Отбор.Элементы);
	
	Параметры = ДанныеКомпоновки.СхемаКомпоновки.Параметры;
	Параметры.Найти("ДатаФормирования").Значение = ТекущаяДатаСеанса();
	Параметры.Найти("УпрощенныйРежим").Значение  = УпрощенныйРежим;
	
	Параметры.Найти("ТекстОбщихПараметровСинхронизации").Значение = ОбменДаннымиСервер.ОписаниеПравилСинхронизацииДанных(УзелИнформационнойБазы);
	Параметры.Найти("ТекстДополнительныхПараметров").Значение     = ТекстДополнительныхПараметров();
	
	Если Не ПустаяСтрока(ПолноеИмяМетаданных) Тогда
		Параметры.Найти("ПредставлениеСписка").Значение = Представление;
		
		ЭлементыОтбора = ДанныеКомпоновки.КомпоновщикНастроек.Настройки.Отбор.Элементы;
		
		Элемент = ЭлементыОтбора.Добавить(Тип("ЭлементОтбораКомпоновкиДанных"));
		Элемент.ЛевоеЗначение  = Новый ПолеКомпоновкиДанных("ПолноеИмяМетаданных");
		Элемент.Представление  = Представление;
		Элемент.ВидСравнения   = ВидСравненияКомпоновкиДанных.Равно;
		Элемент.ПравоеЗначение = ПолноеИмяМетаданных;
		Элемент.Использование  = Истина;
	КонецЕсли;
	
	НастройкиКомпоновщика = ДанныеКомпоновки.КомпоновщикНастроек.ПолучитьНастройки();
	Если УпрощенныйРежим Тогда
		// Отключаем ненужные поля
		СкрываемыеПоля = Новый Структура("КоличествоПоОбщимПравилам, РегистрацияДополнительно, ОбщееКоличество, НеБудетВыгружено, ВыгрузкаОбъектаВозможна");
		Для Каждого Группировка Из НастройкиКомпоновщика.Структура Цикл
			СкрытьПоляВыбора(Группировка.Выбор.Элементы, СкрываемыеПоля)
		КонецЦикла;
		// И переключаем подвал с легендами.
		КоличествоГрупп = НастройкиКомпоновщика.Структура.Количество();
		Если КоличествоГрупп > 0 Тогда
			НастройкиКомпоновщика.Структура.Получить(КоличествоГрупп - 1).Имя = "ПустойПодвал";
		КонецЕсли;
	КонецЕсли;

	КомпоновщикМакета = Новый КомпоновщикМакетаКомпоновкиДанных;
	Макет = КомпоновщикМакета.Выполнить(ДанныеКомпоновки.СхемаКомпоновки, НастройкиКомпоновщика, ДанныеРасшифровки, , Тип("ГенераторМакетаКомпоновкиДанных"));
	ВнешниеНаборыДанных = Новый Структура("ТаблицаМетаданныхСоставаУзла", ДанныеКомпоновки.ТаблицаМетаданныхСоставаУзла);
	
	Процессор = Новый ПроцессорКомпоновкиДанных;
	Процессор.Инициализировать(Макет, ВнешниеНаборыДанных, ДанныеРасшифровки, Истина);
	
	Вывод = Новый ПроцессорВыводаРезультатаКомпоновкиДанныхВТабличныйДокумент;
	Вывод.УстановитьДокумент(Новый ТабличныйДокумент);
	
	Возврат Новый Структура("ТабличныйДокумент, Расшифровка, СхемаКомпоновки",
		Вывод.Вывести(Процессор), ДанныеРасшифровки, ДанныеКомпоновки.СхемаКомпоновки);
КонецФункции

//  Возвращает данные в виде двухуровневого дерева, первый уровень-вид метаданных, второй-объекты.
//  Опирается на значения реквизитов "УзелИнформационнойБазы", "ДополнительнаяРегистрация".
//
//  Параметры:
//      СписокИменМетаданных - Массив - полные имена метаданных для ограничения запроса.
//                                      Может быть коллекцией элементов с полем "ПолноеИмяМетаданных".
//  Возвращаемое значение:
//      ДеревоЗначений - двухуровневое дерево, первый уровень-вид метаданных, второй-объекты.
//
Функция СформироватьДеревоЗначений(СписокИменМетаданных = Неопределено) Экспорт
	УстановитьПривилегированныйРежим(Истина);
	
	ДанныеКомпоновки = ИнициализироватьКомпоновщик(СписокИменМетаданных);
	
	КомпоновщикМакета = Новый КомпоновщикМакетаКомпоновкиДанных;
	Макет = КомпоновщикМакета.Выполнить(ДанныеКомпоновки.СхемаКомпоновки, ДанныеКомпоновки.КомпоновщикНастроек.ПолучитьНастройки(), , , 
		Тип("ГенераторМакетаКомпоновкиДанныхДляКоллекцииЗначений"));
	ВнешниеНаборыДанных = Новый Структура("ТаблицаМетаданныхСоставаУзла", ДанныеКомпоновки.ТаблицаМетаданныхСоставаУзла);
	
	Процессор = Новый ПроцессорКомпоновкиДанных;
	Процессор.Инициализировать(Макет, ВнешниеНаборыДанных, , Истина);
	
	Вывод = Новый ПроцессорВыводаРезультатаКомпоновкиДанныхВКоллекциюЗначений;
	Вывод.УстановитьОбъект(Новый ДеревоЗначений);
	ДеревоРезультата = Вывод.Вывести(Процессор);
	
	Возврат ДеревоРезультата;
КонецФункции

//  Инициализирует весь объект.
//
//  Параметры:
//      Источник - Строка
//               - УникальныйИдентификатор - адрес объекта-источника во временном хранилище или данные.
//
//  Возвращаемое значение:
//    ОбработкаОбъект.ИнтерактивноеИзменениеВыгрузки - ИнтерактивноеИзменениеВыгрузки.
//
Функция ИнициализироватьЭтотОбъект(Знач Источник = "") Экспорт
	
	Если ТипЗнч(Источник)=Тип("Строка") Тогда
		Если ПустаяСтрока(Источник) Тогда
			Возврат ЭтотОбъект;
		КонецЕсли;
		Источник = ПолучитьИзВременногоХранилища(Источник);
	КонецЕсли;
		
	ЗаполнитьЗначенияСвойств(ЭтотОбъект, Источник, , "КомпоновщикОтбораВсехДокументов, ДополнительнаяРегистрация, ДополнительнаяРегистрацияСценарияУзла");
	
	ОбменДаннымиСервер.ЗаполнитьТаблицуЗначений(ДополнительнаяРегистрация, Источник.ДополнительнаяРегистрация);
	ОбменДаннымиСервер.ЗаполнитьТаблицуЗначений(ДополнительнаяРегистрацияСценарияУзла, Источник.ДополнительнаяРегистрацияСценарияУзла);
	
	// Компоновщик инициализируем заново.
	Если ПустаяСтрока(Источник.АдресКомпоновщикаВсехДокументов) Тогда
		Данные = КомпоновщикНастроекОбщегоОтбора();
	Иначе
		Данные = ПолучитьИзВременногоХранилища(Источник.АдресКомпоновщикаВсехДокументов);
	КонецЕсли;
		
	КомпоновщикОтбораВсехДокументов = Новый КомпоновщикНастроекКомпоновкиДанных;
	КомпоновщикОтбораВсехДокументов.Инициализировать(
		Новый ИсточникДоступныхНастроекКомпоновкиДанных(Данные.СхемаКомпоновки));
	КомпоновщикОтбораВсехДокументов.ЗагрузитьНастройки(Данные.Настройки);
	
	Если ПустаяСтрока(Источник.АдресКомпоновщикаВсехДокументов) Тогда
		АдресКомпоновщикаВсехДокументов = ПоместитьВоВременноеХранилище(Данные, Источник.АдресХранилищаФормы);
	Иначе 
		АдресКомпоновщикаВсехДокументов = Источник.АдресКомпоновщикаВсехДокументов;
	КонецЕсли;
		
	Возврат ЭтотОбъект;
КонецФункции

//  Сохраняет данные этого объекта во временном хранилище.
//
//  Параметры:
//      АдресХранилища - Строка
//                     - УникальныйИдентификатор - идентификатор формы хранилища или адрес для помещения.
//
//  Возвращаемое значение:
//      Строка - адрес сохраненного.
//
Функция СохранитьЭтотОбъект(Знач АдресХранилища) Экспорт
	Данные = Новый Структура;
	Для Каждого Мета Из Метаданные().Реквизиты Цикл
		Имя = Мета.Имя;
		Данные.Вставить(Имя, ЭтотОбъект[Имя]);
	КонецЦикла;
	
	ДанныеКомпоновщика = КомпоновщикНастроекОбщегоОтбора();
	Данные.Вставить("АдресКомпоновщикаВсехДокументов", ПоместитьВоВременноеХранилище(ДанныеКомпоновщика, АдресХранилища));
	
	Возврат ПоместитьВоВременноеХранилище(Данные, АдресХранилища);
КонецФункции

//  Возвращает данные компоновщика для общих отборов узла "УзелИнформационнойБазы".
//  Опирается на значения реквизитов "УзелИнформационнойБазы", "ДополнительнаяРегистрация".
//
//  Параметры:
//      АдресСохраненияСхемы - Строка
//                           - УникальныйИдентификатор - адрес временного хранилища для сохранения схемы
//                             компоновки.
//
// Возвращаемое значение:
//      Структура:
//          * Настройки       - НастройкиКомпоновкиДанных - настройки компоновщика.
//          * СхемаКомпоновки - СхемаКомпоновкиДанных     - схема компоновки.
//
Функция КомпоновщикНастроекОбщегоОтбора(АдресСохраненияСхемы = Неопределено) Экспорт
	
	СохраненныйВариант = ВариантВыгрузки;
	ВариантВыгрузки = 1;
	АдресСохранения = ?(АдресСохраненияСхемы = Неопределено, Новый УникальныйИдентификатор, АдресСохраненияСхемы);
	Данные = ИнициализироватьКомпоновщик(Неопределено, Истина, АдресСохранения);
	ВариантВыгрузки = СохраненныйВариант;
	
	Результат = Новый Структура;
	Результат.Вставить("Настройки",  Данные.КомпоновщикНастроек.Настройки);
	Результат.Вставить("СхемаКомпоновки", Данные.СхемаКомпоновки);
	
	Возврат Результат;
КонецФункции

//  Возвращает компоновщик для отборов одного вида метаданных узла "УзелИнформационнойБазы".
//
//  Параметры:
//      ПолноеИмяМетаданных  - Строка - имя таблицы для построения компоновщика. Возможно там будут 
//                                      идентификаторы для "всех документов" или "всех справочников"
//                                      или ссылка на группу.
//      Представление        - Строка - представление объекта в отборе.
//      Отбор                - ОтборКомпоновкиДанных - отбор компоновки для заполнения.
//      АдресСохраненияСхемы - Строка
//                           - УникальныйИдентификатор - адрес временного хранилища для сохранения схемы
//                             компоновки.
//
// Возвращаемое значение:
//      КомпоновщикНастроекКомпоновкиДанных - инициализированный компоновщик.
//
Функция КомпоновщикНастроекПоИмениТаблицы(ПолноеИмяМетаданных, Представление = Неопределено, Отбор = Неопределено, АдресСохраненияСхемы = Неопределено) Экспорт
	
	СхемаКомпоновки = Новый СхемаКомпоновкиДанных;
	
	Источник = СхемаКомпоновки.ИсточникиДанных.Добавить();
	Источник.Имя = "Источник";
	Источник.ТипИсточникаДанных = "local";
	
	ДобавляемыеТаблицы = СоставУкрупненнойГруппыМетаданных(ПолноеИмяМетаданных);
	
	Для Каждого ИмяТаблицы Из ДобавляемыеТаблицы Цикл
		ДобавитьНаборВСхемуКомпоновки(СхемаКомпоновки, ИмяТаблицы, Представление);
	КонецЦикла;
	
	Компоновщик = Новый КомпоновщикНастроекКомпоновкиДанных;
	Компоновщик.Инициализировать(Новый ИсточникДоступныхНастроекКомпоновкиДанных(
		ПоместитьВоВременноеХранилище(СхемаКомпоновки, АдресСохраненияСхемы)));
	
	Если Отбор <> Неопределено Тогда
		ДобавитьЗначенияОтбораКомпоновки(Компоновщик.Настройки.Отбор.Элементы, Отбор.Элементы);
		Компоновщик.Восстановить(СпособВосстановленияНастроекКомпоновкиДанных.ПроверятьДоступность);
	КонецЕсли;
	
	Возврат Компоновщик;
КонецФункции

// Возвращаемое значение:
//     Строка - префикс для получения имен форм текущего объекта.
//
Функция БазовоеИмяДляФормы() Экспорт
	Возврат Метаданные().ПолноеИмя() + "."
КонецФункции

// Возвращаемое значение:
//     Строка - заголовок для формирования представления отбора по всем документам.
//
Функция ЗаголовокГруппыОтбораВсехДокументов() Экспорт
	Возврат НСтр("ru = 'Все документы'");
КонецФункции

// Возвращаемое значение:
//     Строка - заголовок для формирования представления отбора по всем справочникам.
//
Функция ЗаголовокГруппыОтбораВсехСправочников() Экспорт
	Возврат НСтр("ru = 'Все справочники'");
КонецФункции

//  Возвращает описание периода и отбора строкой.
//
//  Параметры:
//      Период - СтандартныйПериод     - период для описания отбора.
//      Отбор  - ОтборКомпоновкиДанных - отбор компоновки данных для описания.
//      ОписаниеПустогоОтбора - Строка - значение, возвращаемое в случае пустого отбора.
// Возвращаемое значение:
//     Строка - представление периода и отбора.
//
Функция ПредставлениеОтбора(Период, Отбор, Знач ОписаниеПустогоОтбора = Неопределено) Экспорт
	Возврат ОбменДаннымиСервер.ПредставлениеОтбораДополненияВыгрузки(Период, Отбор, ОписаниеПустогоОтбора);
КонецФункции

//  Возвращает описание детального отбора по реквизиту "ДополнительнаяРегистрация".
//
//  Параметры:
//      ОписаниеПустогоОтбора - Строка - значение, возвращаемое в случае пустого отбора.
// Возвращаемое значение:
//     Строка - представление детального отбора по реквизиту "ДополнительнаяРегистрация".
//
Функция ПредставлениеДетальногоОтбора(Знач ОписаниеПустогоОтбора=Неопределено)
	Возврат ОбменДаннымиСервер.ПредставлениеДетальногоДополненияВыгрузки(ДополнительнаяРегистрация, ОписаниеПустогоОтбора);
КонецФункции

// Идентификатор служебной группы объектов метаданных "Все документы".
// Возвращаемое значение:
//     Строка - идентификатор служебной группы объектов метаданных "Все документы".
//
Функция ИдентификаторВсехДокументов() Экспорт
	// Не должно пересекаться с полным именем метаданных.
	Возврат ОбменДаннымиСервер.ДополнениеВыгрузкиИдентификаторВсехДокументов();
КонецФункции

// Возвращаемое значение:
//     Строка - идентификатор служебной группы объектов метаданных "Все справочники".
//
Функция ИдентификаторВсехСправочников() Экспорт
	// Не должно пересекаться с полным именем метаданных.
	Возврат ОбменДаннымиСервер.ДополнениеВыгрузкиИдентификаторВсехСправочников();
КонецФункции

//  Добавляет отбор в конец отбора с возможной коррекцией полей.
//
//  Параметры:
//      ЭлементыПриемника - КоллекцияЭлементовОтбораКомпоновкиДанных - приемник.
//      ЭлементыИсточника - КоллекцияЭлементовОтбораКомпоновкиДанных - источник.
//      СоответствиеПолей - Соответствие из КлючИЗначение - определяет состав заменяемых полей отбора:
//                          * Ключ - исходный путь к данным поля. 
//                          * Значение - путь для результата.
//                          Например для замены полей типа.
//                          "Ссылка.Наименование" -> "ОбъектРегистрации.Наименование".
//                          надо передать Новый Структура("Ссылка", "ОбъектРегистрации").
//
Процедура ДобавитьЗначенияОтбораКомпоновки(ЭлементыПриемника, ЭлементыИсточника, СоответствиеПолей = Неопределено) Экспорт
	
	Для Каждого Элемент Из ЭлементыИсточника Цикл
		
		Тип=ТипЗнч(Элемент);
		ЭлементОтбора = ЭлементыПриемника.Добавить(Тип);
		ЗаполнитьЗначенияСвойств(ЭлементОтбора, Элемент);
		Если Тип=Тип("ГруппаЭлементовОтбораКомпоновкиДанных") Тогда
			ДобавитьЗначенияОтбораКомпоновки(ЭлементОтбора.Элементы, Элемент.Элементы, СоответствиеПолей);
			
		ИначеЕсли СоответствиеПолей<>Неопределено Тогда
			ИсходноеПолеСтрокой = Элемент.ЛевоеЗначение;
			Для Каждого КлючЗначение Из СоответствиеПолей Цикл
				КонтрольНовое     = НРег(КлючЗначение.Ключ);
				ДлинаКонтроля     = 1 + СтрДлина(КонтрольНовое);
				КонтрольИсходного = НРег(Лев(ИсходноеПолеСтрокой, ДлинаКонтроля));
				Если КонтрольИсходного=КонтрольНовое Тогда
					ЭлементОтбора.ЛевоеЗначение = Новый ПолеКомпоновкиДанных(КлючЗначение.Значение);
					Прервать;
				ИначеЕсли КонтрольИсходного=КонтрольНовое + "." Тогда
					ЭлементОтбора.ЛевоеЗначение = Новый ПолеКомпоновкиДанных(КлючЗначение.Значение + Сред(ИсходноеПолеСтрокой, ДлинаКонтроля));
					Прервать;
				КонецЕсли;
			КонецЦикла;
			
		КонецЕсли;
		
	КонецЦикла;
	
КонецПроцедуры

//  Возвращает элемент списка значений по представлению.
//
//  Параметры:
//      СписокЗначений - СписокЗначений - список для поиска.
//      Представление  - Строка         - параметр для поиска.
//
// Возвращаемое значение:
//   - ЭлементСпискаЗначений - найденный элемент.
//   - Неопределено  - если элемент не найден.
//
Функция НайтиПоПредставлениюЭлементСписка(СписокЗначений, Представление)
	Для Каждого ЭлементСписка Из СписокЗначений Цикл
		Если ЭлементСписка.Представление=Представление Тогда
			Возврат ЭлементСписка;
		КонецЕсли;
	КонецЦикла;
	Возврат Неопределено;
КонецФункции

//  Производит дополнительную регистрацию по текущим данными объекта.
//
Процедура ЗарегистрироватьДополнительныеИзменения() Экспорт
	
	Если ВариантВыгрузки <= 0 Тогда
		// без изменений
		Возврат;
	КонецЕсли;
	
	ДеревоИзменений = СформироватьДеревоЗначений();
	
	УстановитьПривилегированныйРежим(Истина);
	Для Каждого СтрокаГруппы Из ДеревоИзменений.Строки Цикл
		Для Каждого Строка Из СтрокаГруппы.Строки Цикл
			Если Строка.КоличествоДляВыгрузки > 0 Тогда
				ОбменДаннымиСобытия.ЗарегистрироватьИзмененияДанных(УзелИнформационнойБазы, Строка.ОбъектРегистрации, Ложь);
			КонецЕсли;
		КонецЦикла;
	КонецЦикла;
	
КонецПроцедуры

//  Возвращает список значений из представлений возможных настроек.
//
//  Параметры:
//      УзелОбмена - ПланОбменаСсылка - узел обмена для возвращаемых настроек. Если не указано, то используется 
//                                      текущее значение реквизита "УзелИнформационнойБазы".
//      Варианты - Массив             - если указано, то фильтруем восстанавливаемые настройки по вариантам
//                                      0 - без отбора, 1 - отбор всех документов, 2 - подробный, 3 - сценарий узла.
//
//  Возвращаемое значение:
//      СписокЗначений - возможные настройки.
//
Функция ПрочитатьПредставленияСпискаНастроек(УзелОбмена = Неопределено, Варианты = Неопределено) Экспорт
	
	ПараметрыНастроек = СтруктураПараметровНастроек(УзелОбмена);
	
	УстановитьПривилегированныйРежим(Истина);    
	СписокВариантов = ХранилищеОбщихНастроек.Загрузить(
	ПараметрыНастроек.КлючОбъекта, ПараметрыНастроек.КлючНастроек,
	ПараметрыНастроек, ПараметрыНастроек.Пользователь);
	
	СписокПредставлений = Новый СписокЗначений;
	Если СписокВариантов<>Неопределено Тогда
		Для Каждого Элемент Из СписокВариантов Цикл
			Если Варианты=Неопределено Или Варианты.Найти(Элемент.Значение.ВариантВыгрузки)<>Неопределено Тогда
				СписокПредставлений.Добавить(Элемент.Представление, Элемент.Представление);
			КонецЕсли;
		КонецЦикла;
	КонецЕсли;
	
	Возврат СписокПредставлений;
КонецФункции

//  Восстанавливает значения реквизитов текущего объекта из указанного элемента списка.
//
//  Параметры:
//      Представление       - Строка - представление восстанавливаемых настроек.
//      Варианты            - Массив - если указано, то фильтруем восстанавливаемые настройки по вариантам
//                                     0 - без отбора, 1 - отбор всех документов, 2 - подробный, 3 - сценарий узла.
//      АдресХранилищаФормы - Строка
//                          - УникальныйИдентификатор - необязательный адрес для сохранения.
//
// Возвращаемое значение:
//      Булево - Истина - успешно восстановлено, Ложь - настройка не найдена.
//
Функция ВосстановитьТекущееИзНастроек(Представление, Варианты = Неопределено, АдресХранилищаФормы = Неопределено) Экспорт
	
	СписокВариантов = ПрочитатьСписокНастроек(Варианты);
	ЭлементСписка = НайтиПоПредставлениюЭлементСписка(СписокВариантов, Представление);
	
	Результат = ЭлементСписка<>Неопределено;
	Если Результат Тогда
		НеизменныеДанные = Новый Структура("УзелИнформационнойБазы");
		ЗаполнитьЗначенияСвойств(НеизменныеДанные, ЭтотОбъект);
		ЗаполнитьЗначенияСвойств(ЭтотОбъект, ЭлементСписка.Значение);
		ЗаполнитьЗначенияСвойств(ЭтотОбъект, НеизменныеДанные);
		
		// Компоновщик собираем по частям.
		Данные = КомпоновщикНастроекОбщегоОтбора();
		КомпоновщикОтбораВсехДокументов = Новый КомпоновщикНастроекКомпоновкиДанных;
		КомпоновщикОтбораВсехДокументов.Инициализировать(Новый ИсточникДоступныхНастроекКомпоновкиДанных(Данные.СхемаКомпоновки));
		КомпоновщикОтбораВсехДокументов.ЗагрузитьНастройки(ЭлементСписка.Значение._НастройкиКомпоновщикаОтбораВсехДокументов);
		
		// Инициализация вспомогательного.
		Если АдресХранилищаФормы<>Неопределено Тогда
			АдресКомпоновщикаВсехДокументов = ПоместитьВоВременноеХранилище(Данные, АдресХранилищаФормы);
		КонецЕсли;
	КонецЕсли;
	
	Возврат Результат;
КонецФункции

//  Сохраняет значения реквизитов текущего объекта в настройки с указанным представлением.
//
//  Параметры:
//      Представление         - Строка - представление настроек.
//
Процедура СохранитьТекущееВНастройки(Представление) Экспорт
	СписокВариантов = ПрочитатьСписокНастроек();
	
	ЭлементСписка = НайтиПоПредставлениюЭлементСписка(СписокВариантов, Представление);
	Если ЭлементСписка=Неопределено Тогда
		ЭлементСписка = СписокВариантов.Добавить(, Представление);
		СписокВариантов.СортироватьПоПредставлению();
	КонецЕсли;
	
	СохраняемыеРеквизиты = "УзелИнформационнойБазы, ВариантВыгрузки, ПериодОтбораВсехДокументов, ДополнительнаяРегистрация,
		|ПериодОтбораСценарияУзла, ДополнительнаяРегистрацияСценарияУзла, ПредставлениеОтбораСценарияУзла";
	
	ЭлементСписка.Значение = Новый Структура(СохраняемыеРеквизиты);
	ЗаполнитьЗначенияСвойств(ЭлементСписка.Значение, ЭтотОбъект);
	
	ЭлементСписка.Значение.Вставить("_НастройкиКомпоновщикаОтбораВсехДокументов", КомпоновщикОтбораВсехДокументов.Настройки);
	
	ПараметрыНастроек = СтруктураПараметровНастроек();
	
	УстановитьПривилегированныйРежим(Истина);
	ХранилищеОбщихНастроек.Сохранить(
		ПараметрыНастроек.КлючОбъекта, ПараметрыНастроек.КлючНастроек, 
		СписокВариантов, 
		ПараметрыНастроек, ПараметрыНастроек.Пользователь);
КонецПроцедуры

//  Удаляет вариант настроек из списка.
//
//  Параметры:
//      Представление          - Строка - представление настроек.
//
Процедура УдалитьВариантНастроек(Представление) Экспорт
	СписокВариантов = ПрочитатьСписокНастроек();
	ЭлементСписка = НайтиПоПредставлениюЭлементСписка(СписокВариантов, Представление);
	
	Если ЭлементСписка<>Неопределено Тогда
		СписокВариантов.Удалить(ЭлементСписка);
		СписокВариантов.СортироватьПоПредставлению();
		СохранитьСписокНастроек(СписокВариантов);
	КонецЕсли;
	
КонецПроцедуры

// Возвращает массив имен таблиц метаданных по составному типу параметра "ПолноеИмяМетаданных".
// Опирается на текущее значение реквизита "УзелИнформационнойБазы".
//
// Параметры:
//      ПолноеИмяМетаданных - Строка
//                          - ДеревоЗначений - имя таблицы (например "Справочник.Валюты") или имя
//                            предопределенной группы
//                            (например "ВсеДокументы") или дерево значений, описывающее группу.
//
// Возвращаемое значение:
//      Массив - имена метаданных.
//
Функция СоставУкрупненнойГруппыМетаданных(ПолноеИмяМетаданных) Экспорт
	
	Если ТипЗнч(ПолноеИмяМетаданных) <> Тип("Строка") Тогда
		// Дерево значений с группой отбора. Корень - описание, в строках - имена метаданных.
		ТаблицыСостава = Новый Массив;
		Для Каждого СтрокаГруппы Из ПолноеИмяМетаданных.Строки Цикл
			Для Каждого СтрокаСоставаГруппы Из СтрокаГруппы.Строки Цикл
				ТаблицыСостава.Добавить(СтрокаСоставаГруппы.ПолноеИмяМетаданных);
			КонецЦикла;
		КонецЦикла;
		
	ИначеЕсли ПолноеИмяМетаданных = ИдентификаторВсехДокументов() Тогда
		// Все документы узла
		ВсеДанные = ОбменДаннымиПовтИсп.СоставПланаОбмена(УзелИнформационнойБазы.Метаданные().Имя, Истина, Ложь);
		ТаблицыСостава = ВсеДанные.ВыгрузитьКолонку("ПолноеИмяМетаданных");
		
	ИначеЕсли ПолноеИмяМетаданных = ИдентификаторВсехСправочников() Тогда
		// Все справочники узла
		ВсеДанные = ОбменДаннымиПовтИсп.СоставПланаОбмена(УзелИнформационнойБазы.Метаданные().Имя, Ложь, Истина);
		ТаблицыСостава = ВсеДанные.ВыгрузитьКолонку("ПолноеИмяМетаданных");
		
	Иначе
		// Одиночная таблица метаданных.
		ТаблицыСостава = Новый Массив;
		ТаблицыСостава.Добавить(ПолноеИмяМетаданных);
		
	КонецЕсли;
	
	// Объекты, для которых указано "НеВыгружать", скрываем.
	РежимНеВыгружать = Перечисления.РежимыВыгрузкиОбъектовОбмена.НеВыгружать;
	РежимыВыгрузки   = ОбменДаннымиПовтИсп.ПользовательскийСоставПланаОбмена(УзелИнформационнойБазы);
	
	Позиция = ТаблицыСостава.ВГраница();
	Пока Позиция >= 0 Цикл
		Если РежимыВыгрузки[ТаблицыСостава[Позиция]] = РежимНеВыгружать Тогда
			ТаблицыСостава.Удалить(Позиция);
		КонецЕсли;
		Позиция = Позиция - 1;
	КонецЦикла;
	
	Возврат ТаблицыСостава;
КонецФункции

//  Конструктор таблиц значений. Генерирует таблицу с колонками произвольного типа.
//
//  Параметры:
//      СписокКолонок  - Строка - список имен колонок таблицы через запятую.
//      СписокИндексов - Строка - список индексов таблицы через запятую.
//
// Возвращаемое значение:
//      ТаблицаЗначений - построенная таблица.
//
Функция ТаблицаЗначений(СписокКолонок, СписокИндексов = "")
	ТаблицаРезультата = Новый ТаблицаЗначений;
	
	Для Каждого КлючЗначение Из (Новый Структура(СписокКолонок)) Цикл
		ТаблицаРезультата.Колонки.Добавить(КлючЗначение.Ключ);
	КонецЦикла;
	Для Каждого КлючЗначение Из (Новый Структура(СписокИндексов)) Цикл
		ТаблицаРезультата.Индексы.Добавить(КлючЗначение.Ключ);
	КонецЦикла;
	
	Возврат ТаблицаРезультата;
КонецФункции

//  Добавляет одиночный элемент отбора в список.
//
//  Параметры:
//      ЭлементыОтбора  - ЭлементОтбораКомпоновкиДанных - ссылка на проверяемый объект.
//      ПутьПоляКДанным - Строка - путь к данным для добавляемого элемента.
//      ВидСравнения    - ВидСравненияКомпоновкиДанных - вид сравнения для добавляемого элемента.
//      Значение        - Произвольный - значение сравнения для добавляемого элемента.
//      Представление    -Строка - необязательное представление поля.
//      
Процедура ДобавитьЭлементОтбора(ЭлементыОтбора, ПутьПоляКДанным, ВидСравнения, Значение, Представление = Неопределено)
	
	Элемент = ЭлементыОтбора.Добавить(Тип("ЭлементОтбораКомпоновкиДанных"));
	Элемент.Использование  = Истина;
	Элемент.ЛевоеЗначение  = Новый ПолеКомпоновкиДанных(ПутьПоляКДанным);
	Элемент.ВидСравнения   = ВидСравнения;
	Элемент.ПравоеЗначение = Значение;
	
	Если Представление<>Неопределено Тогда
		Элемент.Представление = Представление;
	КонецЕсли;
КонецПроцедуры

//  Добавляет в схему компоновки набор данных с одним полем "Ссылка" по имени таблицы.
//
//  Параметры:
//      СхемаКомпоновкиДанных - СхемаКомпоновкиДанных - схема, в которую происходит добавление.
//      ИмяТаблицы:           - Строка - имя таблицы данных.
//      Представление:        - Строка - представление для поля "ссылка".
//
Процедура ДобавитьНаборВСхемуКомпоновки(СхемаКомпоновкиДанных, ИмяТаблицы, Представление = Неопределено)
	
	ТекстЗапроса = СтрЗаменить("ВЫБРАТЬ ИмяТаблицыМетаданных.Ссылка КАК Ссылка ИЗ &ИмяТаблицы КАК ИмяТаблицыМетаданных", "&ИмяТаблицы", ИмяТаблицы);
	
	Набор = СхемаКомпоновкиДанных.НаборыДанных.Добавить(Тип("НаборДанныхЗапросСхемыКомпоновкиДанных"));
	Набор.Запрос = ТекстЗапроса;
	Набор.АвтоЗаполнениеДоступныхПолей = Истина;
	Набор.ИсточникДанных = СхемаКомпоновкиДанных.ИсточникиДанных.Получить(0).Имя;
	Набор.Имя = "Набор" + Формат(СхемаКомпоновкиДанных.НаборыДанных.Количество()-1, "ЧН=; ЧГ=");
	
	Поле = Набор.Поля.Добавить(Тип("ПолеНабораДанныхСхемыКомпоновкиДанных"));
	Поле.Поле = "Ссылка";
	Поле.Заголовок = ?(Представление=Неопределено, ОбменДаннымиСервер.ПредставлениеОбъекта(ИмяТаблицы), Представление);
	
КонецПроцедуры

//  Устанавливает наборы данных в схему и инициализирует компоновщик.
//  Опирается на значения реквизитов:
//    "УзелИнформационнойБазы", "ДополнительнаяРегистрация", 
//    "ВариантВыгрузки", "ПериодОтбораВсехДокументов", "КомпоновщикОтбораВсехДокументов".
//
//  Параметры:
//      СписокИменМетаданных - Массив - имена метаданных (деревья значений группы ограничений, служебных
//                                      идентификаторов
//                                      "все документов" или "все НСИ"), для которых будет построена  схема. 
//                                      Если не указано, то для всего состава узла.
//
//      ОграничиватьИспользованиеОтбором - Булево - флаг того, что компоновка будет инициализирована только
//                                                  для отбора элементов выгрузки.
//
//      АдресСохраненияСхемы - Строка
//                           - УникальныйИдентификатор - адрес временного хранилища для сохранения схемы
//                             компоновки.
//
//  Возвращаемое значение:
//      Структура:
//         * ТаблицаМетаданныхСоставаУзла - ТаблицаЗначений - описание состава узла.
//         * СхемаКомпоновки - СхемаКомпоновкиДанных - инициированное значение.
//         * КомпоновщикНастроек - КомпоновщикНастроекКомпоновкиДанных - инициированное значение.
//
Функция ИнициализироватьКомпоновщик(СписокИменМетаданных = Неопределено, ОграничиватьИспользованиеОтбором = Ложь, АдресСохраненияСхемы = Неопределено)
	
	ТаблицаМетаданныхСоставаУзла = ОбменДаннымиПовтИсп.СоставПланаОбмена(УзелИнформационнойБазы.Метаданные().Имя);
	СхемаКомпоновки = ПолучитьМакет("СхемаКомпоновкиДанных");
	
	// Наборы для общего количества.
	ЭлементыНаборыКоличества = СхемаКомпоновки.НаборыДанных.Найти("ОбщееКоличествоЭлементов").Элементы;
	
	// Наборы для каждого нужного вида метаданных.
	ЭлементыНабораИзменения = СхемаКомпоновки.НаборыДанных.Найти("РегистрацияИзменений").Элементы;
	Пока ЭлементыНабораИзменения.Количество() > 1 Цикл
		// [0] - Описание полей
		ЭлементыНабораИзменения.Удалить(ЭлементыНабораИзменения[1]);
	КонецЦикла;
	ИсточникДанных = СхемаКомпоновки.ИсточникиДанных.Получить(0).Имя;
	
	// Фильтр того, чего от нас хотят.
	ФильтрИменМетаданных = Новый Соответствие;
	Если СписокИменМетаданных <> Неопределено Тогда
		Если ТипЗнч(СписокИменМетаданных) = Тип("Массив") Тогда
			Для Каждого МетаИмя Из СписокИменМетаданных Цикл
				ФильтрИменМетаданных.Вставить(МетаИмя, Истина);
			КонецЦикла;
		Иначе
			Для Каждого Элемент Из СписокИменМетаданных Цикл
				ФильтрИменМетаданных.Вставить(Элемент.ПолноеИмяМетаданных, Истина);
			КонецЦикла;
		КонецЕсли;
	КонецЕсли;
	
	ШаблонЗапросаИзменений =
	"ВЫБРАТЬ РАЗЛИЧНЫЕ РАЗРЕШЕННЫЕ
	|	ПсевдонимТаблицыРегистрации.Ссылка  КАК ОбъектРегистрации,
	|	&ПолноеИмяТаблицыМетаданныхТип      КАК ОбъектРегистрацииТип,
	|	&ПричинаРегистрацииАвтоматически    КАК ПричинаРегистрации
	|ИЗ
	|	&ПолноеИмяТаблицыМетаданных КАК ПсевдонимТаблицыРегистрации
	|ГДЕ ПсевдонимТаблицыРегистрации.Узел = &УзелИнформационнойБазы";
	
	ШаблонЗапросаКоличество =
	"ВЫБРАТЬ РАЗРЕШЕННЫЕ
	|	&ПолноеИмяТаблицыМетаданныхТип                 КАК Тип,
	|	КОЛИЧЕСТВО(ПсевдонимТаблицыРегистрации.Ссылка) КАК ОбщееКоличество
	|ИЗ
	|	&ПолноеИмяТаблицыМетаданных КАК ПсевдонимТаблицыРегистрации";
	
	// Автоматические изменения и количества всегда.
	Для Каждого Строка Из ТаблицаМетаданныхСоставаУзла Цикл
		
		ПолноеИмяМетаданных = Строка.ПолноеИмяМетаданных;
		Если СписокИменМетаданных <> Неопределено И ФильтрИменМетаданных[ПолноеИмяМетаданных] <> Истина Тогда
			Продолжить;
		КонецЕсли;
		
		СтрокаЗаменыТип = СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку("Тип(%1)", ПолноеИмяМетаданных);
		СтрокаЗаменыТаблицаИзменений = СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку("%1.Изменения", ПолноеИмяМетаданных);
		СтрокаЗаменыТаблица = СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку("%1", ПолноеИмяМетаданных);
		ИмяНабораПоМетаданным = СтрЗаменить(ПолноеИмяМетаданных, ".", "_");
		
		ИмяНабора = "Автоматически_" + ИмяНабораПоМетаданным;
		Если ЭлементыНабораИзменения.Найти(ИмяНабора) = Неопределено Тогда
			
			Набор = ЭлементыНабораИзменения.Добавить(Тип("НаборДанныхЗапросСхемыКомпоновкиДанных"));
			Набор.АвтоЗаполнениеДоступныхПолей = Не ОграничиватьИспользованиеОтбором;
			Набор.ИсточникДанных = ИсточникДанных;
			Набор.Имя = ИмяНабора;
			
			ТекстЗапроса = СтрЗаменить(ШаблонЗапросаИзменений, "&ПолноеИмяТаблицыМетаданныхТип", СтрокаЗаменыТип);
			ТекстЗапроса = СтрЗаменить(ТекстЗапроса, "&ПолноеИмяТаблицыМетаданных", СтрокаЗаменыТаблицаИзменений);
			Набор.Запрос = ТекстЗапроса;
			
		КонецЕсли;
		
		ИмяНабора = "Количество_" + ИмяНабораПоМетаданным;
		Если ЭлементыНаборыКоличества.Найти(ИмяНабора) = Неопределено Тогда
			
			Набор = ЭлементыНаборыКоличества.Добавить(Тип("НаборДанныхЗапросСхемыКомпоновкиДанных"));
			Набор.АвтоЗаполнениеДоступныхПолей = Истина;
			Набор.ИсточникДанных = ИсточникДанных;
			Набор.Имя = ИмяНабора;
		
			ТекстЗапроса = СтрЗаменить(ШаблонЗапросаКоличество, "&ПолноеИмяТаблицыМетаданныхТип", СтрокаЗаменыТип);
			ТекстЗапроса = СтрЗаменить(ТекстЗапроса, "&ПолноеИмяТаблицыМетаданных", СтрокаЗаменыТаблица);
			Набор.Запрос = ТекстЗапроса;
			
		КонецЕсли;
		
	КонецЦикла;
	
	// Варианты дополнительных изменений.
	Если ВариантВыгрузки = 1 Тогда
		// Общий отбор по шапке
		ТаблицаДополнительныхИзменений = ТаблицаЗначений("ПолноеИмяМетаданных, Отбор, Период, ВыборПериода");
		Строка = ТаблицаДополнительныхИзменений.Добавить();
		Строка.ПолноеИмяМетаданных = ИдентификаторВсехДокументов();
		Строка.ВыборПериода        = Истина;
		Строка.Период              = ПериодОтбораВсехДокументов;
		Строка.Отбор               = КомпоновщикОтбораВсехДокументов.Настройки.Отбор;
		
	ИначеЕсли ВариантВыгрузки = 2 Тогда
		// Детальный отбор
		ТаблицаДополнительныхИзменений = ДополнительнаяРегистрация;
		
	Иначе
		// Без дополнительных изменений вообще.
		ТаблицаДополнительныхИзменений = Новый ТаблицаЗначений;
		
	КонецЕсли;
	
	ШаблонЗапросаДополнительно =
	"ВЫБРАТЬ РАЗРЕШЕННЫЕ
	|	ПсевдонимТаблицыРегистрации.Ссылка  КАК ОбъектРегистрации,
	|	&ПолноеИмяТаблицыМетаданныхТип КАК ОбъектРегистрацииТип,
	|	&ПричинаРегистрацииДополнительно   КАК ПричинаРегистрации
	|ИЗ
	|	&ПолноеИмяТаблицыМетаданных КАК ПсевдонимТаблицыРегистрации";
	
	// Дополнительные изменения
	Для Каждого Строка Из ТаблицаДополнительныхИзменений Цикл
		ПолноеИмяМетаданных = Строка.ПолноеИмяМетаданных;
		ТекущийОтбор = Строка.Отбор; // ОтборКомпоновкиДанных
		
		Если СписокИменМетаданных <> Неопределено И ФильтрИменМетаданных[ПолноеИмяМетаданных] <> Истина Тогда
			Продолжить;
		КонецЕсли;
		
		ДобавляемыеТаблицы = СоставУкрупненнойГруппыМетаданных(ПолноеИмяМетаданных);
		Для Каждого ИмяДобавляемойТаблицы Из ДобавляемыеТаблицы Цикл
			Если СписокИменМетаданных <> Неопределено И ФильтрИменМетаданных[ИмяДобавляемойТаблицы] <> Истина Тогда
				Продолжить;
			КонецЕсли;
			
			СтрокаЗаменыТип = СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку("Тип(%1)", ИмяДобавляемойТаблицы);
			
			ИмяНабора = "Дополнительно_" + СтрЗаменить(ИмяДобавляемойТаблицы, ".", "_");
			Если ЭлементыНабораИзменения.Найти(ИмяНабора) = Неопределено Тогда 
				
				Набор = ЭлементыНабораИзменения.Добавить(Тип("НаборДанныхЗапросСхемыКомпоновкиДанных"));
				Набор.ИсточникДанных = ИсточникДанных;
				Набор.АвтоЗаполнениеДоступныхПолей = Истина;
				Набор.Имя = ИмяНабора;
				
				ТекстЗапроса = СтрЗаменить(ШаблонЗапросаДополнительно, "&ПолноеИмяТаблицыМетаданныхТип", СтрокаЗаменыТип);
				ТекстЗапроса = СтрЗаменить(ТекстЗапроса, "&ПолноеИмяТаблицыМетаданных", ИмяДобавляемойТаблицы);
				Набор.Запрос = ТекстЗапроса;
				
				// Добавляем дополнительные наборы для получения данных их табличных частей отбора.
				ПараметрыДобавления = Новый Структура;
				ПараметрыДобавления.Вставить("ИмяДобавляемойТаблицы", ИмяДобавляемойТаблицы);
				ПараметрыДобавления.Вставить("СхемаКомпоновки",       СхемаКомпоновки);
				ДобавитьДополнительныеНаборыКомпоновкиТабличныхЧастей(ТекущийОтбор.Элементы, ПараметрыДобавления)
				
			КонецЕсли;
			
		КонецЦикла;
	КонецЦикла;
	
	// Общие параметры
	Параметры = СхемаКомпоновки.Параметры;
	Параметры.Найти("УзелИнформационнойБазы").Значение = УзелИнформационнойБазы;
	
	ПараметрАвтоматически = Параметры.Найти("ПричинаРегистрацииАвтоматически");
	ПараметрАвтоматически.Значение = НСтр("ru = 'По общим правилам'");
	
	ПараметрДополнительно = Параметры.Найти("ПричинаРегистрацииДополнительно");
	ПараметрДополнительно.Значение = НСтр("ru = 'Дополнительно'");
	
	ПараметрПоСсылке = Параметры.Найти("ПричинаРегистрацииПоСсылке");
	ПараметрПоСсылке.Значение = НСтр("ru = 'По ссылке'");
	
	Если ОграничиватьИспользованиеОтбором Тогда
		Поля = СхемаКомпоновки.НаборыДанных.Найти("РегистрацияИзменений").Поля;
		Ограничение = Поля.Найти("ОбъектРегистрацииТип").ОграничениеИспользования;
		Ограничение.Условие = Истина;
		Ограничение = Поля.Найти("ПричинаРегистрации").ОграничениеИспользования;
		Ограничение.Условие = Истина;
		
		Поля = СхемаКомпоновки.НаборыДанных.Найти("ТаблицаМетаданныхСоставаУзла").Поля;
		Ограничение = Поля.Найти("ПредставлениеСписка").ОграничениеИспользования;
		Ограничение.Условие = Истина;
		Ограничение = Поля.Найти("Представление").ОграничениеИспользования;
		Ограничение.Условие = Истина;
		Ограничение = Поля.Найти("ПолноеИмяМетаданных").ОграничениеИспользования;
		Ограничение.Условие = Истина;
		Ограничение = Поля.Найти("Периодический").ОграничениеИспользования;
		Ограничение.Условие = Истина;
	КонецЕсли;
	
	КомпоновщикНастроек = Новый КомпоновщикНастроекКомпоновкиДанных;
	
	КомпоновщикНастроек.Инициализировать(Новый ИсточникДоступныхНастроекКомпоновкиДанных(
		ПоместитьВоВременноеХранилище(СхемаКомпоновки, АдресСохраненияСхемы)));
	КомпоновщикНастроек.ЗагрузитьНастройки(СхемаКомпоновки.НастройкиПоУмолчанию);
	
	Если ТаблицаДополнительныхИзменений.Количество() > 0 Тогда 
		
		Если ОграничиватьИспользованиеОтбором Тогда
			КореньНастроек = КомпоновщикНастроек.ФиксированныеНастройки;
		Иначе
			КореньНастроек = КомпоновщикНастроек.Настройки;
		КонецЕсли;
		
		// Добавляем настройки для отбора дополнительных данных.
		ГруппаОтбора = КореньНастроек.Отбор.Элементы.Добавить(Тип("ГруппаЭлементовОтбораКомпоновкиДанных"));
		ГруппаОтбора.Использование = Истина;
		ГруппаОтбора.ТипГруппы = ТипГруппыЭлементовОтбораКомпоновкиДанных.ГруппаИли;
		
		ЭлементыОтбора = ГруппаОтбора.Элементы;
		
		// Авторегистрацию подтягиваем всегда.
		ДобавитьЭлементОтбора(ГруппаОтбора.Элементы, "ПричинаРегистрации", ВидСравненияКомпоновкиДанных.Равно, ПараметрАвтоматически.Значение);
		ДобавитьЭлементОтбора(ГруппаОтбора.Элементы, "ПричинаРегистрации", ВидСравненияКомпоновкиДанных.Равно, ПараметрПоСсылке.Значение);
		
		Для Каждого Строка Из ТаблицаДополнительныхИзменений Цикл
			ПолноеИмяМетаданных = Строка.ПолноеИмяМетаданных;
			ТекущийОтбор = Строка.Отбор; // ОтборКомпоновкиДанных
			ПериодОтбора = Строка.Период; // СтандартныйПериод
			
			Если СписокИменМетаданных <> Неопределено И ФильтрИменМетаданных[ПолноеИмяМетаданных] <> Истина Тогда
				Продолжить;
			КонецЕсли;
			
			ДобавляемыеТаблицы = СоставУкрупненнойГруппыМетаданных(ПолноеИмяМетаданных);
			Для Каждого ИмяДобавляемойТаблицы Из ДобавляемыеТаблицы Цикл
				Если СписокИменМетаданных <> Неопределено И ФильтрИменМетаданных[ИмяДобавляемойТаблицы] <> Истина Тогда
					Продолжить;
				КонецЕсли;
				
				ГруппаОтбора = ЭлементыОтбора.Добавить(Тип("ГруппаЭлементовОтбораКомпоновкиДанных"));
				ГруппаОтбора.Использование = Истина;
				
				ДобавитьЭлементОтбора(ГруппаОтбора.Элементы, "ПолноеИмяМетаданных", ВидСравненияКомпоновкиДанных.Равно, ИмяДобавляемойТаблицы);
				ДобавитьЭлементОтбора(ГруппаОтбора.Элементы, "ПричинаРегистрации",  ВидСравненияКомпоновкиДанных.Равно, ПараметрДополнительно.Значение);
				
				Если Строка.ВыборПериода Тогда
					ДатаНачала    = ПериодОтбора.ДатаНачала;
					ДатаОкончания = ПериодОтбора.ДатаОкончания;
					Если ДатаНачала <> '00010101' Тогда
						ДобавитьЭлементОтбора(ГруппаОтбора.Элементы, "ОбъектРегистрации.Дата", ВидСравненияКомпоновкиДанных.БольшеИлиРавно, ДатаНачала);
					КонецЕсли;
					Если ДатаОкончания <> '00010101' Тогда
						ДобавитьЭлементОтбора(ГруппаОтбора.Элементы, "ОбъектРегистрации.Дата", ВидСравненияКомпоновкиДанных.МеньшеИлиРавно, ДатаОкончания);
					КонецЕсли;
				КонецЕсли;
				
				// Добавляем элементы отбора с коррекцией полей "Ссылка" -> "ОбъектРегистрации".
				ПараметрыДобавления = Новый Структура;
				ПараметрыДобавления.Вставить("ИмяДобавляемойТаблицы", ИмяДобавляемойТаблицы);
				ДобавитьДополнительныеОтборыКомпоновкиТабличныхЧастей(
					ГруппаОтбора.Элементы, ТекущийОтбор.Элементы, ПараметрыДобавления);
			КонецЦикла;
		КонецЦикла;
		
	КонецЕсли;
	
	Возврат Новый Структура("ТаблицаМетаданныхСоставаУзла,СхемаКомпоновки,КомпоновщикНастроек", 
		ТаблицаМетаданныхСоставаУзла, СхемаКомпоновки, КомпоновщикНастроек);
КонецФункции

Процедура ДобавитьДополнительныеНаборыКомпоновкиТабличныхЧастей(ЭлементыИсточника, ПараметрыДобавления)
	
	ИмяДобавляемойТаблицы = ПараметрыДобавления.ИмяДобавляемойТаблицы;
	СхемаКомпоновки       = ПараметрыДобавления.СхемаКомпоновки;
	
	ОбщийНабор     = СхемаКомпоновки.НаборыДанных.Найти("РегистрацияИзменений");
	ИсточникДанных = СхемаКомпоновки.ИсточникиДанных.Получить(0).Имя; 
	
	МетаданныеОбъекта = Метаданные.НайтиПоПолномуИмени(ИмяДобавляемойТаблицы);
	Если МетаданныеОбъекта = Неопределено Тогда
		ВызватьИсключение СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(НСтр("ru = 'Некорректное имя метаданных ""%1"" для регистрации на узле ""%2""'"),
				ИмяДобавляемойТаблицы, УзелИнформационнойБазы);
	КонецЕсли;
	
	ШаблонТекстаЗапроса = 
	"ВЫБРАТЬ РАЗРЕШЕННЫЕ
	|	Ссылка                            КАК ОбъектРегистрации,
	|	&ИмяДобавляемойТаблицыТип         КАК ОбъектРегистрацииТип,
	|	&ПричинаРегистрацииДополнительно  КАК ПричинаРегистрации
	|	,&ВсеПоляТабличнойЧасти
	|ИЗ
	|	&ИмяДобавляемойТаблицы";
	
	Для Каждого Элемент Из ЭлементыИсточника Цикл
		
		Если ТипЗнч(Элемент) = Тип("ГруппаЭлементовОтбораКомпоновкиДанных") Тогда 
			ДобавитьДополнительныеНаборыКомпоновкиТабличныхЧастей(Элемент.Элементы, ПараметрыДобавления);
			Продолжить;
		КонецЕсли;
		
		// Это элемент, смотрим чтобы попало на нашу табличку.
		ИмяПоля = Элемент.ЛевоеЗначение;
		Если СтрНачинаетсяС(ИмяПоля, "Ссылка.") Тогда
			ИмяПоля = Сред(ИмяПоля, 8);
		ИначеЕсли СтрНачинаетсяС(ИмяПоля, "ОбъектРегистрации.") Тогда
			ИмяПоля = Сред(ИмяПоля, 19);
		Иначе
			Продолжить;
		КонецЕсли;
			
		Позиция = СтрНайти(ИмяПоля, "."); 
		ИмяТаблицы   = Лев(ИмяПоля, Позиция - 1);
		МетаданныеТабличнойЧасти = МетаданныеОбъекта.ТабличныеЧасти.Найти(ИмяТаблицы);
			
		Если Позиция = 0 Тогда
			// Отбор к шапке, получим через ссылку.
			Продолжить;
		ИначеЕсли МетаданныеТабличнойЧасти = Неопределено Тогда
			// Табличная часть есть, но не наша.
			Продолжить;
		КонецЕсли;
		
		// Наша табличная часть
		ПутьКДанным = Сред(ИмяПоля, Позиция + 1);
		Если СтрНачинаетсяС(ПутьКДанным + ".", "Ссылка.") Тогда
			// Переадресуем на головную таблицу.
			Продолжить;
		КонецЕсли;
		
		Псевдоним = СтрЗаменить(ИмяДобавляемойТаблицы, ".", "") + ИмяТаблицы;
		ИмяНабора = "Дополнительно_" + Псевдоним;
		Набор = ОбщийНабор.Элементы.Найти(ИмяНабора);
		Если Набор <> Неопределено Тогда
			Продолжить;
		КонецЕсли;
		
		Набор = ОбщийНабор.Элементы.Добавить(Тип("НаборДанныхЗапросСхемыКомпоновкиДанных"));
		Набор.АвтоЗаполнениеДоступныхПолей = Истина;
		Набор.ИсточникДанных = ИсточникДанных;
		Набор.Имя = ИмяНабора;
		
		ВсеПоляТабличнойЧасти = РеквизитыТабличнойЧастиДляЗапроса(МетаданныеТабличнойЧасти, Псевдоним);
		ИмяДобавляемойТаблицыЗапросаДопОтборов = СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку("%1.%2", ИмяДобавляемойТаблицы, ИмяТаблицы);
		
		СтрокаЗамены = СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку("Тип(%1)", ИмяДобавляемойТаблицы);
		ТекстЗапроса = СтрЗаменить(ШаблонТекстаЗапроса, "&ИмяДобавляемойТаблицыТип", СтрокаЗамены);
		ТекстЗапроса = СтрЗаменить(ТекстЗапроса, ",&ВсеПоляТабличнойЧасти", ВсеПоляТабличнойЧасти.ПоляЗапроса);
		ТекстЗапроса = СтрЗаменить(ТекстЗапроса, "&ИмяДобавляемойТаблицы", ИмяДобавляемойТаблицыЗапросаДопОтборов);
		Набор.Запрос = ТекстЗапроса;
		
		Для Каждого ИмяПоля Из ВсеПоляТабличнойЧасти.ИменаПолей Цикл
			Поле = Набор.Поля.Найти(ИмяПоля);
			Если Поле = Неопределено Тогда
				Поле = Набор.Поля.Добавить(Тип("ПолеНабораДанныхСхемыКомпоновкиДанных"));
				Поле.ПутьКДанным = ИмяПоля;
				Поле.Поле        = ИмяПоля;
			КонецЕсли;
			Поле.ОграничениеИспользованияРеквизитов.Условие = Истина;
			Поле.ОграничениеИспользованияРеквизитов.Поле    = Истина;
			Поле.ОграничениеИспользования.Условие = Истина;
			Поле.ОграничениеИспользования.Поле    = Истина;
		КонецЦикла;
		
	КонецЦикла;
		
КонецПроцедуры

Процедура ДобавитьДополнительныеОтборыКомпоновкиТабличныхЧастей(ЭлементыПриемника, ЭлементыИсточника, ПараметрыДобавления)
	
	ИмяДобавляемойТаблицы = ПараметрыДобавления.ИмяДобавляемойТаблицы;
	МетаОбъекта = Метаданные.НайтиПоПолномуИмени(ИмяДобавляемойТаблицы);
	
	Для Каждого Элемент Из ЭлементыИсточника Цикл
		// Ветка разбора аналогична ветке в ДобавитьДополнительныеНаборыКомпоновкиТабличныхЧастей.
		
		Тип = ТипЗнч(Элемент); 
		Если ТипЗнч(Элемент) = Тип("ГруппаЭлементовОтбораКомпоновкиДанных") Тогда
			// Группу копируем
			ЭлементОтбора = ЭлементыПриемника.Добавить(Тип);
			ЗаполнитьЗначенияСвойств(ЭлементОтбора, Элемент);
			
			ДобавитьДополнительныеОтборыКомпоновкиТабличныхЧастей(
				ЭлементОтбора.Элементы, Элемент.Элементы, ПараметрыДобавления);
			Продолжить;
		КонецЕсли;
		
		// Это элемент, смотрим чтобы попало на нашу табличку.
		ИмяПоля = Строка(Элемент.ЛевоеЗначение);
		Если ИмяПоля = "Ссылка" Тогда
			ЭлементОтбора = ЭлементыПриемника.Добавить(Тип);
			ЗаполнитьЗначенияСвойств(ЭлементОтбора, Элемент);
			ЭлементОтбора.ЛевоеЗначение = Новый ПолеКомпоновкиДанных("ОбъектРегистрации");
			Продолжить;
			
		ИначеЕсли СтрНачинаетсяС(ИмяПоля, "Ссылка.") Тогда
			ИмяПоля = Сред(ИмяПоля, 8);
			
		ИначеЕсли СтрНачинаетсяС(ИмяПоля, "ОбъектРегистрации.") Тогда
			ИмяПоля = Сред(ИмяПоля, 19);
			
		Иначе
			ЭлементОтбора = ЭлементыПриемника.Добавить(Тип);
			ЗаполнитьЗначенияСвойств(ЭлементОтбора, Элемент);
			Продолжить;
			
		КонецЕсли;
			
		Позиция    = СтрНайти(ИмяПоля, "."); 
		ИмяТаблицы = Лев(ИмяПоля, Позиция - 1);
		
		МетаТабличнаяЧасть = МетаОбъекта.ТабличныеЧасти.Найти(ИмяТаблицы);
		МетаРеквизиты      = МетаОбъекта.Реквизиты.Найти(ИмяТаблицы);
			
		Если Позиция = 0
			Или МетаРеквизиты <> Неопределено
			Или ОбщегоНазначения.ЭтоСтандартныйРеквизит(МетаОбъекта.СтандартныеРеквизиты, ИмяТаблицы) Тогда
			// Отбор к шапке, будет получен через ссылку.
			ЭлементОтбора = ЭлементыПриемника.Добавить(Тип);
			ЗаполнитьЗначенияСвойств(ЭлементОтбора, Элемент);
			ЭлементОтбора.ЛевоеЗначение = Новый ПолеКомпоновкиДанных("ОбъектРегистрации." + ИмяПоля);
			Продолжить;
			
		ИначеЕсли МетаТабличнаяЧасть = Неопределено Тогда
			// Табличная часть указана, но не наша. Усиливаем отбор.
			ЭлементОтбора = ЭлементыПриемника.Добавить(Тип);
			ЗаполнитьЗначенияСвойств(ЭлементОтбора, Элемент);
			ЭлементОтбора.ЛевоеЗначение  = Новый ПолеКомпоновкиДанных("ПолноеИмяМетаданных");
			ЭлементОтбора.ВидСравнения   = ВидСравненияКомпоновкиДанных.Равно;
			ЭлементОтбора.Использование  = Истина;
			ЭлементОтбора.ПравоеЗначение = "";
			
			Продолжить;
		КонецЕсли;
		
		// Отбор к табличной части
		ПутьКДанным = Сред(ИмяПоля, Позиция + 1);
		Если СтрНачинаетсяС(ПутьКДанным + ".", "Ссылка.") Тогда
			// Переадресуем на головную таблицу.
			ЭлементОтбора = ЭлементыПриемника.Добавить(Тип);
			ЗаполнитьЗначенияСвойств(ЭлементОтбора, Элемент);
			ЭлементОтбора.ЛевоеЗначение = Новый ПолеКомпоновкиДанных("ОбъектРегистрации." + Сред(ПутьКДанным, 8));
			
		ИначеЕсли ПутьКДанным <> "НомерСтроки" И ПутьКДанным <> "Ссылка"
			И МетаТабличнаяЧасть.Реквизиты.Найти(ПутьКДанным) = Неопределено Тогда
			// Табличная часть совпадает, но реквизит не наш. Усиливаем отбор.
			ЭлементОтбора = ЭлементыПриемника.Добавить(Тип);
			ЗаполнитьЗначенияСвойств(ЭлементОтбора, Элемент);
			ЭлементОтбора.ЛевоеЗначение  = Новый ПолеКомпоновкиДанных("ПолноеИмяМетаданных");
			ЭлементОтбора.ВидСравнения   = ВидСравненияКомпоновкиДанных.Равно;
			ЭлементОтбора.Использование  = Истина;
			ЭлементОтбора.ПравоеЗначение = "";
			
		Иначе
			// Корректируем имя
			ЭлементОтбора = ЭлементыПриемника.Добавить(Тип);
			ЗаполнитьЗначенияСвойств(ЭлементОтбора, Элемент);
			ПутьКДанным = СтрЗаменить(ИмяДобавляемойТаблицы + ИмяТаблицы, ".", "") + ПутьКДанным;
			ЭлементОтбора.ЛевоеЗначение = Новый ПолеКомпоновкиДанных(ПутьКДанным);
		КонецЕсли;
		
	КонецЦикла;
	
КонецПроцедуры

// Только для внутреннего использования.
//
// Параметры:
//   МетаТабличнаяЧасть - ОбъектМетаданныхТабличнаяЧасть - метаданные табличной части.
//   Префикс - Строка - префикс имени реквизита.
//
Функция РеквизитыТабличнойЧастиДляЗапроса(Знач МетаТабличнаяЧасть, Знач Префикс = "")
	
	ПоляЗапроса = ", НомерСтроки КАК " + Префикс + "НомерСтроки
	              |, Ссылка      КАК " + Префикс + "Ссылка
	              |";
	
	ИменаПолей  = Новый Массив;
	ИменаПолей.Добавить(Префикс + "НомерСтроки");
	ИменаПолей.Добавить(Префикс + "Ссылка");
	
	Для Каждого МетаРеквизит Из МетаТабличнаяЧасть.Реквизиты Цикл
		Имя       = МетаРеквизит.Имя;
		Псевдоним = Префикс + Имя;
		ПоляЗапроса = ПоляЗапроса + ", " + Имя + " КАК " + Псевдоним + Символы.ПС;
		ИменаПолей.Добавить(Псевдоним);
	КонецЦикла;
	
	Возврат Новый Структура("ПоляЗапроса, ИменаПолей", ПоляЗапроса, ИменаПолей);
КонецФункции

//  Возвращает параметры-ключи для сохранения настроек в разрезе плана обмена для всех пользователей.
//
//  Параметры:
//      УзелОбмена - ПланОбменаСсылка - ссылка на узел обмена для возвращаемых настроек. Если не указано, то
//                                      используется  текущее значение реквизита "УзелИнформационнойБазы".
//
//  Возвращаемое значение:
//      ОписаниеНастроек - описание настроек.
//
Функция СтруктураПараметровНастроек(УзелОбмена = Неопределено)
	Узел = ?(УзелОбмена=Неопределено,  УзелИнформационнойБазы, УзелОбмена);
	
	Мета = Узел.Метаданные();
	
	Представление = Мета.РасширенноеПредставлениеОбъекта;
	Если ПустаяСтрока(Представление) Тогда
		Представление = Мета.ПредставлениеОбъекта;
	КонецЕсли;
	Если ПустаяСтрока(Представление) Тогда
		Представление = Строка(Мета);
	КонецЕсли;
	
	ПараметрыНастроек = Новый ОписаниеНастроек();
	ПараметрыНастроек.Представление = Представление;
	ПараметрыНастроек.КлючОбъекта   = "ВариантыНастроекИнтерактивнойВыгрузки";
	ПараметрыНастроек.КлючНастроек  = Мета.Имя;
	ПараметрыНастроек.Пользователь  = "*";
	
	Возврат ПараметрыНастроек;
КонецФункции

// Возвращает список значений настроек для текущего значения "УзелИнформационнойБазы".
//
// Параметры:
//      Варианты - Массив - если указано, то фильтруем восстанавливаемые настройки по вариантам
//                          0 - без отбора, 1 - отбор всех документов, 2 - подробный, 3 - сценарий узла.
//
//  Возвращаемое значение:
//      СписокЗначений - настройки.
//
Функция ПрочитатьСписокНастроек(Варианты = Неопределено)
	ПараметрыНастроек = СтруктураПараметровНастроек();
	
	УстановитьПривилегированныйРежим(Истина);
	СписокВариантов = ХранилищеОбщихНастроек.Загрузить(
		ПараметрыНастроек.КлючОбъекта, ПараметрыНастроек.КлючНастроек, 
		ПараметрыНастроек, ПараметрыНастроек.Пользователь);
		
	Если СписокВариантов=Неопределено Тогда
		Результат = Новый СписокЗначений;
	ИначеЕсли Варианты=Неопределено Тогда
		Результат = СписокВариантов;
	Иначе
		Результат = СписокВариантов;
		Позиция = Результат.Количество() - 1;
		Пока Позиция>=0 Цикл
			Если Варианты.Найти(Результат[Позиция].Значение.ВариантВыгрузки)=Неопределено Тогда
				Результат.Удалить(Позиция);
			КонецЕсли;
			Позиция = Позиция - 1
		КонецЦикла;
	КонецЕсли;
		
	Возврат Результат;
КонецФункции

// Сохраняет список значений настроек для текущего значения "УзелИнформационнойБазы".
//
//  Параметры:
//      СписокВариантов - СписокЗначений - сохраняемый список вариантов.
//
Процедура СохранитьСписокНастроек(СписокВариантов)
	ПараметрыНастроек = СтруктураПараметровНастроек();
	
	УстановитьПривилегированныйРежим(Истина);
	Если СписокВариантов.Количество()=0 Тогда
		ХранилищеОбщихНастроек.Удалить(
			ПараметрыНастроек.КлючОбъекта, ПараметрыНастроек.КлючНастроек, ПараметрыНастроек.Пользователь);
	Иначе
		ХранилищеОбщихНастроек.Сохранить(
			ПараметрыНастроек.КлючОбъекта, ПараметрыНастроек.КлючНастроек, 
			СписокВариантов, 
			ПараметрыНастроек, ПараметрыНастроек.Пользователь);
	КонецЕсли;        
КонецПроцедуры

// Возвращает описание варианта всех дополнительных параметров.
//
Функция ТекстДополнительныхПараметров()
	
	Если ВариантВыгрузки = 0 Тогда
		// Все автоматические данные
		Возврат НСтр("ru = 'Без дополнительных данных.'");
		
	ИначеЕсли ВариантВыгрузки = 1 Тогда
		ТекстВсеДокументы = ЗаголовокГруппыОтбораВсехДокументов();
		Результат = ПредставлениеОтбора(ПериодОтбораВсехДокументов, КомпоновщикОтбораВсехДокументов, ТекстВсеДокументы);
		Возврат СтрЗаменить(Результат, "ОбъектРегистрации.", ТекстВсеДокументы + ".")
		
	ИначеЕсли ВариантВыгрузки = 2 Тогда
		Возврат ПредставлениеДетальногоОтбора();
		
	КонецЕсли;
	
	Возврат "";
КонецФункции

// Возвращает структуру с реквизитами объекта.
//
Функция ЭтотОбъектВСтруктуруДляФонового() Экспорт
	СтруктураРезультата = Новый Структура();

	Для Каждого Мета Из Метаданные().Реквизиты Цикл
		ИмяРеквизита = Мета.Имя;
		Если ИмяРеквизита = "КомпоновщикОтбораВсехДокументов" Тогда
			Продолжить;
		КонецЕсли;
		
		СтруктураРезультата.Вставить(ИмяРеквизита, ЭтотОбъект[ИмяРеквизита]);
	КонецЦикла;
	// Передаем пусто - этот элемент далее явно исключается из обработки.
	СтруктураРезультата.Вставить("КомпоновщикОтбораВсехДокументов");

	// Отдельно настройки КомпоновщикОтбораВсехДокументов - там только отбор.
	СтруктураРезультата.Вставить("НастройкиКомпоновщикаОтбораВсехДокументов", КомпоновщикОтбораВсехДокументов.Настройки);
	
	Возврат СтруктураРезультата;
КонецФункции

Процедура СкрытьПоляВыбора(ЭлементыГруппировки, Знач СкрываемыеПоля)
	ТипГруппа = Тип("ГруппаВыбранныхПолейКомпоновкиДанных");
	Для Каждого ЭлементГруппировки Из ЭлементыГруппировки Цикл
		Если ТипЗнч(ЭлементГруппировки)=ТипГруппа Тогда
			СкрытьПоляВыбора(ЭлементГруппировки.Элементы, СкрываемыеПоля)
		Иначе
			ИмяПоля = СтрЗаменить(Строка(ЭлементГруппировки.Поле), ".", "");
			Если Не ПустаяСтрока(ИмяПоля) И СкрываемыеПоля.Свойство(ИмяПоля) Тогда
				ЭлементГруппировки.Использование = Ложь;
			КонецЕсли;
		КонецЕсли;
	КонецЦикла;
КонецПроцедуры

#КонецОбласти

#Иначе
ВызватьИсключение НСтр("ru = 'Недопустимый вызов объекта на клиенте.'");
#КонецЕсли